package org.vergil.utils.secure;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * AES 加解密方法类
 * @author: vergil
 * @Date: 2018/4/22
 * @since 1.0.0
 */
public class AES {

    private static final String ALGORITHM = "AES";
    private Key key;
    private Cipher cipher;

    AES(byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException {
        if (null == key || key.length == 0) {
            throw new NullPointerException("key can't be empty");
        }
        if (key.length != 16) {
            throw new IllegalArgumentException("key length must be 16");
        }
        Key keySpec = new SecretKeySpec(key, ALGORITHM);
        this.key = keySpec;
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        this.cipher = cipher;
    }

    public byte[] encrypt(byte[] content) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        if (null == content || content.length == 0) {
            throw new NullPointerException("content can't be empty");
        }
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(content);
    }

    public String encrypt(String content) {
        if (null == content || content.isEmpty()) {
            throw new NullPointerException("content can't be empty");
        }
        try {
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] contentBytes =  cipher.doFinal(content.getBytes());
            return Base64.getEncoder().encodeToString(contentBytes);
        } catch (Exception e) {
            return null;
        }
    }

    public byte[] decrypt(byte[] content) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        if (null == content || content.length == 0) {
            throw new NullPointerException("content can't be empty");
        }
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(content);
    }

    public String decrypt(String content) {
        if (null == content || content.isEmpty()) {
            throw new NullPointerException("content can't be empty");
        }
        try {
            cipher.init(Cipher.DECRYPT_MODE, key);
            return new String(cipher.doFinal(Base64.getDecoder().decode(content)));
        } catch (Exception e) {
            return null;
        }
    }
}
